puts the controller to sleep for a period of 1 to 65535 units of 2.3 seconds.
As the name implies, Sleep is the long version of Nap. Certain applications, like data logging, require the PIC's attention at infrequent intervals; once a minute, once an hour, even once a day. Sleep makes it possible to reduce current draw to 3 µA (other than any loads driven by I/O pins) between these tasks. When it's time to perform another task, the PIC wakes up automatically.
To use Sleep, put the duration desired (1 to 65,535 units of 2.3 seconds each) into the hiB and lowB, and call the subroutine. Sleep changes hiB and lowB to their two's complements, sets the timer prescaler to divide by 128, assigns it to the watchdog timer, and puts the PIC to sleep.
Every 2.3 seconds thereafter, the PIC wakes up briefly. It looks at the timeout (to) and power-down (pd) bits of the status register. If the reset was caused by a watchdog timeout awakening the PIC out of sleep (to = 0, pd = 0), the program increments lowB and hiB. If the 16-bit register overflows, it's time to wake up. If not, the PIC goes back to sleep. As you can see from the example listing, Sleep requires more than just the subroutine to work. The device directive must include wdt_on to enable the watchdog timer. The code at the beginning of the program must examine the to and pd bits and decide what to do. And, although it's not shown in the example, the program must clear the watchdog timer (clr wdt) frequently enough to prevent it from interrupting the running program. How frequently depends on the value in the prescaler and whether or not the rest o f the program uses the prescaler with the RTCC.
The safest answer is to clear the watchdog at least every 9 ms. Then, no matter how the option register is set up or what the actual speed of the watchdog's oscillator is, the wdt will never overflow.
Another issue concerns what to do about the wdt-invoked reset and its effect on the I/O pins. During a reset, all pins are set to input. If the PIC is driving a load during its nap, there will be a brief glitch as the TRIS registers are reset. It is best not to drive loads directly during naps, but to rely on pullup or pulldown resistors to do the job instead. Finally, remember that all computed jumps and called subroutines must be in the first 256 words of a program-memory page. In this case, that would include both Nap and the decision-making code in start.
In the discussion of Nap, we ignored the issue of accuracy. For most applications, small errors in the length of a nap are not an issue. With Sleep, it could be a different story. If you construct a data logger and expect it to take a reading every 12 hours on the dot by using Sleep as an interval timer, you're in for a disappointment.
Manufacturing variations in the PIC, and changes in supply voltage and operating temperature affect the period of the watchdog timer's oscillat or. At extremes of temperature and voltage, it can range from 9 ms to 40 ms. This makes it a pretty unreliable alarm clock. It seems likely that the BASIC Stamp performs a self-calibration to reduce this error. Since the Stamp always has math functions at its disposal, this makes sense. In the interest of keeping this code short and clear, I've omitted a calibration step.
To see Sleep in operation, either run the program with the PSIM simulator, or connect the circuit below to an erasable PIC. (The downloader won't work properly in this case, because Sleep relies on a power-on reset occurring. The downloader is reset by MCLR.) Assemble and program the PIC with SLEEP.SRC. Every 2 hours (approximately) the state of the LED will toggle. To change the period, change the numbers stored in hiB and lowB in the portion of the program labeled main.
; ; *************************************************************************** ; *** Bubble Software Parallax to PIC Source Converter. Copyright 1999. *** ; *** http://www.bubblesoftonline.com email: sales@picnpoke.com *** ; *************************************************************************** ; ; SLEEP period ; Puts the PIC to sleep for 1 to 65535 units of 2.3 seconds. ; The 2.3-second value is approximate. Wide variations in operating temperature ; or supply voltage can double or halve this figure. See the discussion in the ; Nap program listing. ; Device data and reset vector: Note that the watchdog timer is ON. P = pic16c55 #include <16c55.inc> ; processor assembler definitions _CONFIG _xt_osc & _wdt_on & _protect_off reset start org 8 hiB Res 1 lowB Res 1 org 0 sleep COMF hiB ; Take twos complement COMF lowB ; of the 16-bit counter INCF lowB BTFSC status,z ; If zero, lowB overflowed, INCF hiB ; so carry into hiB. MOVLW d'15' ; Assign prescaler (div 128) OPTION ; to wdt, then write to option. SLEEP ; Go to sleep. start MOVLW d'0' ; Make RB all outputs for LEDs. TRIS 6h CLRW ; At the beginning of the program, BTFSC status,pd ; we set up a Branch-type routine IORLW d'1' ; to take action based on the BTFSC status,to ; power-down (pd) and timeout (to) IORLW d'2' ; bits. ADDWF pcl ; | to | pd| GOTO count_dn ; | 0 | 0 | wdt wakeup: count down. GOTO watch_fail ; | 0 | 1 | wdt timeout: handle it. GOTO mclr_pin ; | 1 | 0 | mclr wakeup: handle it. GOTO main ; | 1 | 1 | power 1st on: goto main. ; This code executes when power is first applied to the PIC (after start). ; It consists of a loop in which the PIC sleeps for 2 hours, then inverts port RB. main MOVLW 0x0C ; Load 3125 (0C35 hex) MOVWF hiB MOVLW 0x35 ; into 16-bit counter. MOVWF lowB CALL Sleep ; Hibernate for 3125 x 2.304 secs. MOVLW d'255' ; Wake up after 2 hours, invert RB. XORWF 6h GOTO main ; Do it again. ; When the PIC wakes up from a wdt timeout, it executes this code, which ; increments the 16-bit value in lowB and hiB, and determines whether it's ; time to wake up. If it's not, the PIC goes back to sleep. If it is, the program ; returns to resume execution at the instruction following call Sleep. count_dn INCF lowB ; lowB = lowB+1. BTFSC status,z ; Overflow in lowB? INCFSZ hiB ; Yes: hiB=hiB+1, overflow?. SLEEP ; No overflow: back to sleep. RETLW 0h ; Overflow. Return to caller ; In an actual application, this code would contain instructions for dealing ; with a reset pulse waking the PIC out of sleep. Here, we have an empty ; routine that just returns to the main loop. mclr_pin RETLW 0h ; In an actual application, this code would contain instructions for dealing ; with a watchdog-timer timeout during program execution. Here, we have an ; empty routine that just returns to the main loop. watch_fail RETLW 0h
; SLEEP period ; Puts the PIC to sleep for 1 to 65535 units of 2.3 seconds. ; The 2.3-second value is approximate. Wide variations in operating temperature ; or supply voltage can double or halve this figure. See the discussion in the ; Nap program listing. org 8 hiB ds 1 lowB ds 1 ; Device data and reset vector: Note that the watchdog timer is ON. device pic16c55,xt_osc,wdt_on,protect_off reset start org 0 Sleep NOT hiB ; Take twos complement NEG lowB ; of the 16-bit counter snz ; If zero, lowB overflowed, inc hiB ; so carry into hiB. mov w,#15 ; Assign prescaler (div 128) mov option,w ; to wdt, then write to option. sleep ; Go to sleep. ; SLEEP (cont) start mov !rb,#0 ; Make RB all outputs for LEDs. clr w ; At the beginning of the program, snb pd ; we set up a Branch-type routine OR w,#1 ; to take action based on the snb to ; power-down (pd) and timeout (to) OR w,#2 ; bits. jmp pc+w ; | to | pd| jmp count_dn ; | 0 | 0 | wdt wakeup: count down. jmp wdt_fail ; | 0 | 1 | wdt timeout: handle it. jmp mclr_pin ; | 1 | 0 | mclr wakeup: handle it. jmp main ; | 1 | 1 | power 1st on: goto main. ; This code executes when power is first applied to the PIC (after start). ; It consists of a loop in which the PIC sleeps for 2 hours, then inverts port RB. main mov hiB,#0Ch ; Load 3125 (0C35 hex) mov lowB,#35h ; into 16-bit counter. call Sleep ; Hibernate for 3125 x 2.304 secs. XOR rb,#255 ; Wake up after 2 hours, invert RB. jmp main ; Do it again. ; When the PIC wakes up from a wdt timeout, it executes this code, which ; increments the 16-bit value in lowB and hiB, and determines whether it's ; time to wake up. If it's not, the PIC goes back to sleep. If it is, the program ; returns to resume execution at the instruction following call Sleep. count_dn inc lowB ; lowB = lowB+1. snz ; Overflow in lowB? incsz hiB ; Yes: hiB=hiB+1, overflow?. sleep ; No overflow: back to sleep. ret ; Overflow. Return to caller ; In an actual application, this code would contain instructions for dealing ; with a reset pulse waking the PIC out of sleep. Here, we have an empty ; routine that just returns to the main loop. mclr_pin ret ; In an actual application, this code would contain instructions for dealing ; with a watchdog-timer timeout during program execution. Here, we have an ; empty routine that just returns to the main loop. wdt_fail ret
See also:
Interested:
See: